﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml.Linq;
using System.Xml.Serialization;
using DentScan2.DB;

namespace DentScan2.WebApp.Classes
{
    [Serializable]
    public class Damage
    {

        public Guid? DamageId
        {
            get;
            set;
        }

        public int? DamageIdentifier
        {
            get;
            set;
        }

        public Car Car
        {
            get;
            set;
        }
        public int? Kilometers
        {
            get;
            set;
        }
        public Guid? InsurerId
        {
            get;
            set;
        }
        public string InsurerName
        {
            get;
            set;
        }


        public Guid? EvaluatorId
        {
            get;
            set;
        }
        public string EvaluatorName
        {
            get;
            set;
        }

        public string EvaluatorPerson
        {
            get;
            set;
        }
        public string DocumentNumber
        {
            get;
            set;
        }
        public string DamageCode
        {
            get;
            set;
        }
        public string Dossier
        {
            get;
            set;
        }
        public DateTime? DamageDate
        {
            get;
            set;
        }
        public string DamageDateStr
        {
            get
            {
                return this.DamageDate.HasValue ? this.DamageDate.Value.ToShortDateString() : "";
            }
        }


        public string UserPhone
        {
            get;
            set;
        }
        public DateTime? ExpertiseDate
        {
            get;
            set;
        }

        public DateTime? RepairDate
        {
            get;
            set;
        }


        public bool ExpertChecked
        {
            get;
            set;
        }

        public string ExpertiseDateStr
        {
            get
            {
                return this.ExpertiseDate.HasValue ? this.ExpertiseDate.Value.ToShortDateString() : "";
            }
            set
            {
            }
        }

        public string RepairDateStr
        {
            get
            {
                return this.RepairDate.HasValue ? this.RepairDate.Value.ToShortDateString() : "";
            }
            set
            {
            }
        }

        public int? DifficultyPercent
        {
            get;
            set;
        }


        public decimal? Discount
        {
            get;
            set;
        }

        public decimal? Total
        {
            get;
            set;
        }

        public decimal? TotalDiscount
        {
            get
            {
                if (Total == null || Discount == null)
                    return null;
                else
                    return Total.Value - Discount.Value * Total.Value / 100.0M;
            }
            set
            {

            }
        }

        public decimal? VAT
        {
            get;
            set;
        }

        public decimal? VatValue
        {
            get
            {
                if (VAT == null || TotalDiscount == null)
                    return null;
                else
                    return VAT.Value * TotalDiscount.Value / 100.0M;
            }
            set
            {

            }
        }

        public decimal? TotalWithVat
        {
            get
            {
                if (TotalDiscount == null || VatValue == null)
                    return null;
                else
                    return TotalDiscount.Value + VatValue;
            }
            set
            {

            }
        }

        public int? DisassemblyTime
        {
            get;
            set;
        }


        public int? DisassemblyPrice
        {
            get;
            set;
        }

        public int? PreparationTime
        {
            get;
            set;
        }

        public Guid? ExpertiseCountryId
        {
            get;
            set;
        }

        public Guid? ExpertiseDistrictId
        {
            get;
            set;
        }

        public Guid? ExpertisePlaceId
        {
            get;
            set;
        }

        public string TechName
        {
            get;
            set;
        }

        public string TechPhone
        {
            get;
            set;
        }

        public bool JustHours
        {
            get;
            set;
        }

        public List<DamageDetail> DamageDetails
        {
            get;
            set;
        }

        public string Currency
        {
            get;
            set;
        }

        public CalcData CalcData
        {
            get;
            set;
        }

        public int AdditionalMaterialsTotal
        {
            get;
            set;
        }

        public string OwnData
        {
            get;
            set;
        }

        public Damage()
        {
            DamageDetails = new List<DamageDetail>();
            Car = new Car();
            CalcData = new CalcData();
        }

        public Damage(DB.Damage damage)
        {
            DamageDetails = new List<DamageDetail>();
            foreach (var dd in damage.DamageDetails.Where(dd => !dd.IsDel))
                DamageDetails.Add(new DamageDetail(dd));
            Car = new Car(damage.Car);
            this.DamageIdentifier = damage.DamageIdentifier;
            this.DamageCode = damage.DamageCode;
            this.DamageDate = damage.DamageDate;
            this.DamageId = damage.DamageId;
            this.DifficultyPercent = damage.DifficultyPercent;
            this.Discount = damage.Discount;
            this.DocumentNumber = damage.DocumentNumber;
            this.Dossier = damage.Dossier;
            this.EvaluatorId = damage.Evaluator.EvaluatorId;
            this.EvaluatorName = damage.Evaluator.EvaluatorName;
            this.EvaluatorPerson = damage.EvaluatorPerson;
            this.ExpertiseDate = damage.ExpertiseDate;
            this.RepairDate = damage.RepairDate;            
            this.ExpertiseCountryId = damage.City.District.CountryId;
            this.ExpertiseDistrictId = damage.City.DistrictId;
            this.ExpertisePlaceId = damage.City.CityId;
            this.InsurerId = damage.Insurer.InsurerId;
            this.InsurerName = damage.Insurer.InsurerName;
            this.Kilometers = damage.Kilometers;
            this.DisassemblyTime = damage.DisassemblyTime;
            this.DisassemblyPrice = damage.DisassemblyPrice;
            this.PreparationTime = damage.PreparationTime;
            this.TechName = damage.TechName;
            this.TechPhone = damage.TechPhone;
            this.Total = damage.Total;
            this.UserPhone = damage.UserPhone;
            this.ExpertChecked = damage.ExpertChecked;
            this.AdditionalMaterialsTotal = damage.AdditionalMaterialsTotal;
            this.OwnData = damage.OwnData;
            this.CalcData = CalcData.FromXml(damage.CalcData);

        }


        public void SaveToDB(DLDataContext dl, Guid userId)
        {
            this.Car.SaveToDB(dl);
            if (this.DamageId == null)
                Insert(dl, userId);
            else
                Update(dl);

            foreach (var dd in dl.DamageDetails.Where(dd => dd.DamageId == this.DamageId).ToArray())
            {
                dd.IsDel = true;
                dd.LastEditDate = DateTime.UtcNow;
            }
            dl.SubmitChanges();
            foreach (var dd in this.DamageDetails)
                dd.SaveToDB(dl, this.DamageId.Value);
        }

        private void Update(DLDataContext dl)
        {
            var item = dl.Damages.Where(d => d.DamageId == this.DamageId).First();
            item.DamageCode = this.DamageCode;
            item.DamageDate = this.DamageDate;
            item.DifficultyPercent = this.DifficultyPercent;
            item.Discount = this.Discount;
            item.DocumentNumber = this.DocumentNumber;
            item.Dossier = this.Dossier;
            item.EvaluatorId = this.EvaluatorId;

            item.EvaluatorPerson = this.EvaluatorPerson;
            item.ExpertiseDate = this.ExpertiseDate;
            item.RepairDate = this.RepairDate;
            item.ExpertisePlaceId = this.ExpertisePlaceId;
            item.InsurerId = this.InsurerId;
            item.Kilometers = this.Kilometers;
            item.DisassemblyTime = this.DisassemblyTime.HasValue ? this.DisassemblyTime.Value : 0;
            item.DisassemblyPrice = this.DisassemblyPrice.HasValue ? this.DisassemblyPrice.Value : 0;
            item.PreparationTime = this.PreparationTime.HasValue ? this.PreparationTime.Value : 0;
            item.TechName = this.TechName;
            item.TechPhone = this.TechPhone;
            item.Total = this.Total;
            item.UserPhone = this.UserPhone;
            item.ExpertChecked = this.ExpertChecked;
            item.AdditionalMaterialsTotal = this.AdditionalMaterialsTotal;
            item.OwnData = this.OwnData;
            item.IsDel = false;
            item.LastEditDate = DateTime.UtcNow;
            dl.SubmitChanges();
        }

        private void Insert(DLDataContext dl, Guid userId)
        {
            var item = new DB.Damage();
            item.DamageId = Guid.NewGuid();
            item.CarId = this.Car.CarId.Value;
            item.DamageCode = this.DamageCode;
            item.DamageDate = this.DamageDate;
            item.DifficultyPercent = this.DifficultyPercent;
            item.Discount = this.Discount;
            item.DocumentNumber = this.DocumentNumber;
            item.Dossier = this.Dossier;
            item.EvaluatorId = this.EvaluatorId;

            item.EvaluatorPerson = this.EvaluatorPerson;
            item.ExpertiseDate = this.ExpertiseDate;
            item.RepairDate = this.RepairDate;
            item.ExpertisePlaceId = this.ExpertisePlaceId;
            item.InsurerId = this.InsurerId;
            item.Kilometers = this.Kilometers;
            item.DisassemblyTime = this.DisassemblyTime.HasValue ? this.DisassemblyTime.Value : 0;
            item.DisassemblyPrice = this.DisassemblyPrice.HasValue ? this.DisassemblyPrice.Value : 0;
            item.PreparationTime = this.PreparationTime.HasValue ? this.PreparationTime.Value : 0;
            item.TechName = this.TechName;
            item.TechPhone = this.TechPhone;
            item.Total = this.Total;
            item.UserPhone = this.UserPhone;
            item.UserId = userId;
            item.ExpertChecked = this.ExpertChecked;
            item.AdditionalMaterialsTotal = this.AdditionalMaterialsTotal;
            item.OwnData = this.OwnData;
            item.IsDel = false;
            item.LastEditDate = DateTime.UtcNow;
            item.CalcData = this.CalcData.GetSerialized();
            dl.Damages.InsertOnSubmit(item);
            dl.SubmitChanges();
            var dmg = dl.Damages.First(d => d.DamageId == item.DamageId);
            this.DamageId = dmg.DamageId;
            this.DamageIdentifier = dmg.DamageIdentifier;
        }

        public XElement GetXml()
        {
            XmlSerializer xs = new XmlSerializer(this.GetType());
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            xs.Serialize(sw, this);
            return XElement.Parse(sb.ToString());
        }

        public static Damage FromXml(XElement xml)
        {
            XmlSerializer xs = new XmlSerializer(typeof(Damage));
            StringReader sr = new StringReader(xml.ToString());
            return (Damage)xs.Deserialize(sr);
        }

    }
}